﻿using Cl.Utils.Extention;
using Cl.Utils.Primitives.Class;
using Cl.Utils.Primitives.Const;
using Cl.Utils.Primitives.Enum;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;

namespace Cl.Utils.Helper
{
    public class JwtHelper
    {

        /// <summary>
        /// 创建JWT
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public static string CreateJWTToken(GlobalUserInfoModel user)
        {

            var jwtConfig = ConfigHelper.GetJwtConfig();
            var JWToken = new JwtSecurityToken(
                    issuer: jwtConfig.Issuer,
                    audience: jwtConfig.Audience,
                    claims: GetUserClaims(user),
                    notBefore: new DateTimeOffset(DateTime.Now).DateTime,
                    expires: new DateTimeOffset(DateTime.Now.AddSeconds(jwtConfig.Expires)).DateTime,
                    signingCredentials: new SigningCredentials(new SymmetricSecurityKey(Encoding.ASCII.GetBytes(jwtConfig.Secret)), SecurityAlgorithms.HmacSha256Signature)
                );
            var token = new JwtSecurityTokenHandler().WriteToken(JWToken);
            return token;
        }

        /// <summary>
        /// 构建claim
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        private static IEnumerable<Claim> GetUserClaims(GlobalUserInfoModel user)
        {
            IEnumerable<Claim> claims = new Claim[]
            {
                new Claim(ClaimConst.UserId , user.UserId.ToString()),
                new Claim(ClaimConst.UserName , user.UserName),
                new Claim(ClaimConst.Account , user.Account.ToString()),
                new Claim(ClaimConst.ClientType, user.ClientType)
            };
            return claims;
        }

        /// <summary>
        /// 解析JWT
        /// </summary>
        /// <param name="token"></param>
        public static GlobalUserInfoModel JWTDecode(string? token)
        {
            try
            {
                if (string.IsNullOrEmpty(token))
                {
                    return new GlobalUserInfoModel();
                }

                // 去掉 "Bearer " 前缀
                var jwtToken = token.Substring(7);
                // 解析JWT令牌
                var handler = new JwtSecurityTokenHandler();
                if (!handler.CanReadToken(jwtToken))
                {
                    return new GlobalUserInfoModel();
                }
                var securityToken = handler.ReadJwtToken(jwtToken);
                if (securityToken == null)
                {
                    return new GlobalUserInfoModel();
                }

                // 提取数据
                GlobalUserInfoModel user = new GlobalUserInfoModel();
                var UserId = securityToken.Claims.FirstOrDefault(c => c.Type == ClaimConst.UserId)?.Value;
                if (!string.IsNullOrEmpty(UserId))
                    user.UserId = UserId.ToLimsInt32();
                var UserName = securityToken.Claims.FirstOrDefault(c => c.Type == ClaimConst.UserName)?.Value;
                if (!string.IsNullOrEmpty(UserName))
                    user.UserName = UserName;
                var Account = securityToken.Claims.FirstOrDefault(c => c.Type == ClaimConst.Account)?.Value;
                if (!string.IsNullOrEmpty(Account))
                    user.Account = Account;
                return user;
            }
            catch (Exception ex)
            {
                LoggerHelper.Error(LogEnum.System, "解析JWT异常", ex);
                return new GlobalUserInfoModel();
            }
        }

        /// <summary>
        /// 根HTTP请求解析JWT
        /// </summary>
        /// <param name="token"></param>
        public static GlobalUserInfoModel JWTDecodeByHttp(IHttpContextAccessor? httpContext)
        {
            try
            {
                if (httpContext?.HttpContext?.Request?.Headers == null)
                {
                    return new GlobalUserInfoModel();
                }

                var authHeader = httpContext.HttpContext.Request.Headers["Authorization"].FirstOrDefault();
                if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer "))
                {
                    return new GlobalUserInfoModel();
                }
                return JWTDecode(authHeader);
            }
            catch (Exception ex)
            {
                LoggerHelper.Error(LogEnum.System, "解析HttpJWT异常", ex);
                return new GlobalUserInfoModel();
            }
        }

        /// <summary>
        /// 是否过期
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        public static bool IsExpired(string token)
        {
            try
            {
                var handler = new JwtSecurityTokenHandler();
                var jwt = handler.ReadJwtToken(token);

                if (jwt == null)
                {
                    return true;
                }

                if (jwt.ValidTo < DateTime.Now)
                {
                    return true;
                }
                return false;
            }
            catch
            {
                return true;
            }
        }

        public static bool HasAllowAnonymous(ActionExecutingContext context)
        {
            var endpoint = context.HttpContext.GetEndpoint();
            if (endpoint?.Metadata?.GetMetadata<IAllowAnonymous>() != null)
            {
                return true;
            }
            return false;
        }
    }
}
